package com.wangyu.springsecuritydemo.config;

import com.wangyu.springsecuritydemo.service.security.UserSecurityDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;

/**
 * security配置类
 *
 * @Author wangyu
 * @Date 2019/2/18 11:44
 * @Version 1.0
 */
@Configuration
//启用Spring Security的Web安全支持
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
        //系统中不需要进行权限控制的地址
        .antMatchers("/").permitAll()
        .antMatchers("/user/**").hasRole("USER").and()
        // 其它访问都要验证权限
//        .anyRequest().authenticated().and()
        //设定登录页的url地址，它不进行权限控制
        .formLogin()
        //当用户成功登录时，它们将被重定向到先前请求的需要身份认证的页面。有一个由 loginPage()指定的自定义“/登录”页面，每个人都可以查看它
        .loginPage("/login")
        .defaultSuccessUrl("/user") //登录成功的url，访问首页
        .and().logout().logoutUrl("/logout")
        .logoutSuccessUrl("/login");
  }

  /**
   * 自定义UserDetailsService
   */
  @Bean
  public UserSecurityDetailsService userSecurityDetailsService() {
    return new UserSecurityDetailsService();
  }

  /**
   * 密码加密 BCrypt算法将salt随机并混入最终加密后的密码，验证时也无需单独提供之前的salt，从而无需单独处理salt问题。 BCryptPasswordEncoder
   * 是在哪里使用的？ 登录时用到了 DaoAuthenticationProvider ，它有一个方法 #additionalAuthenticationChecks(UserDetails
   * userDetails, UsernamePasswordAuthenticationToken authentication)，此方法用来校验从数据库取得的用户信息和用户输入的信息是否匹配。
   */
  @Bean
  public BCryptPasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
  }
}
